/*******************************************************************************
 * Copyright (c) 2012, 2013 XML-Print Project.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     XML-Print Project - initial API and implementation
 ******************************************************************************/
package info.xmlprint.ui.format;

import info.xmlprint.core.format.Format;
import info.xmlprint.ui.message.GuiMessages;

import java.util.ArrayList;
import java.util.HashMap;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Spinner;

/**
 *  
 */
public class PageLayoutComposite extends GuiCommon implements IFormatSetup {
	private Composite comp;
	
	//
	private Group groupColumnSelection;
	private Spinner spinnerColumnCount;
	
	private Group groupColumns;
	private Spinner spinnercolumngap;
	private Combo combocolumngap;
	private ArrayList<Column> columnlist;
		
	private Spinner spinnercolumnwidth;
	private Combo combocolumnwidth, combocolumndirection;
	
	private Format format, formatForSetup;

	private String standardReference;
	private boolean isFormatStandard;

	private String[] itemListColumndirections_local;
	
	private Button inheritButton;

	/**
	 * test
	 */
	public static void main(String[] args) {
		Display display = Display.getDefault();
		Shell shell = new Shell(display);
		new PageLayoutComposite(shell, SWT.NULL, new Format());

		shell.setLayout(new FillLayout());
		shell.layout();

		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
	}

	public PageLayoutComposite(org.eclipse.swt.widgets.Composite parent, int style,
			Format f) {
		format = f;
		formatForSetup = f.objClone();
		comp = new Composite(parent, style);
		languageInit();
		initGUI();
	}

	private void languageInit() {
		// font-style
		{
			String[] original = new String[] { "inherit", "ltr", "rtl" };

			itemListColumndirections_local = new String[] {
					GuiMessages.Stileditor_PageLayout_Column_Directions_Inherit,
					GuiMessages.Stileditor_PageLayout_Column_Directions_LTR,
					GuiMessages.Stileditor_PageLayout_Column_Directions_RTL };

			addInternationalMap("column-directions", original,
					itemListColumndirections_local);
		}
	}

	/*
	 * Einstellungswerte lesen und Format aktualisieren
	 */
	@Override
	public Format getFormat() {
		String s;

		// wenn Format standardwerte übernehmen soll, werde mit
		// standardReference
		// gespeichert.
		standardReference = "%@%";
		isFormatStandard = false;
		if (this.format.getType().equals("standard")) {
			standardReference = "";
			isFormatStandard = true;
		}

		String attrName = null;

		{
			attrName = "column-count";
			s = spinnerColumnCount.getText();
			setFormatNewValue(attrName, spinnerColumnCount, s);
		}

		//
		{
			attrName = "column-gaps";
			s = "";
			for (int i = 0; i < ghm.size()-1; i++) { //"-1" because we need one gap less than columns
				s += " " + readSpinnerCombo((Spinner) ghm.get(i)[0], (Combo) ghm.get(i)[1]);	
			}
			
			setFormatNewValue(attrName, (Combo) ghm.get(0)[1], s.trim());
		}

		{
			attrName = "column-widths";
			s = "";
			for (int i = 0; i < cwhm.size(); i++) {
				s += " " + readSpinnerCombo((Spinner) cwhm.get(i)[0], (Combo) cwhm.get(i)[1]);
			}
			
			if (s.contains("auto")) {
				if (s.contains(".")) // "auto" and a unit selected => error
					MessageDialog.openError(new Shell(), GuiMessages.Stileditor_Error_Error, "Wenn Sie \"auto\" verwenden, so gilt dies stets für alle Spalten!");
				s = "auto"; // set value to a single "auto"
			}
			
			if (!s.isEmpty())
				setFormatNewValue(attrName, (Combo) cwhm.get(0)[1], s.trim());
		}
		
		{
			attrName = "column-directions";
			s = "";
			for (int i = 0; i < cdhm.size(); i++) {
				String t = readCombo((Combo) cdhm.get(i));
				t = getOriginalValue(attrName, t);
				s += " " + t;
			}
			
			if (!s.isEmpty())
				setFormatNewValue(attrName, (Combo) cdhm.get(0), s.trim());
		}

		return this.format;
	}

	private void setFormatNewValue(String attrName, Control control,
			String controlValue) {
		if (!isFormatStandard
				&& controlValue.equals(this.format.getFormatGroup()
						.getStandardFormat().getAttribute(attrName))) {
			controlValue = standardReference;
		}

		if (!control.isEnabled()) {
			this.format.setInherit(attrName, true);
		} else {
			this.format.setInherit(attrName, false);
		}
		this.format.setAttribute(attrName, controlValue);
	}

	@Override
	public Composite getComp() {
		return comp;
	}

	private void initGUI() {
		HashMap<String, Control[]> hm = new HashMap<String, Control[]>();
		
		comp.setLayout(new GridLayout(4, false));

		{
			groupColumnSelection = new Group(comp, SWT.NONE);
			groupColumnSelection.setLayout(new GridLayout(4, false));
			groupColumnSelection.setText(GuiMessages.Stileditor_PageLayout_Column_Title);
			groupColumnSelection.setLayoutData(getGD(GridData.FILL_HORIZONTAL, 4, 0, 0));

			addLabel(groupColumnSelection,
					GuiMessages.Stileditor_PageLayout_Column_Count + ":");
			spinnerColumnCount = new Spinner(groupColumnSelection, SWT.NONE);
			spinnerColumnCount.setLayoutData(getGD(0, 1, 50, 0));
			spinnerColumnCount.setDigits(0);
			spinnerColumnCount.setIncrement(1);
			spinnerColumnCount.setMinimum(1);
			spinnerColumnCount.setMaximum(10);
			
			// add inherit Checkbox
			inheritButton = new Button(groupColumnSelection, SWT.CHECK);
			inheritButton.setText(GuiMessages.Stileditor_Gui_Inherit);

			// add Standard Checkbox
			Button standardButton = new Button(groupColumnSelection, SWT.PUSH);
			standardButton.setText(GuiMessages.Stileditor_Gui_Standard);
			
			// set Standard Checkbox and controlsvalue
			hm = new HashMap<String, Control[]>();
			hm.put("column-count", new Control[] { spinnerColumnCount });
				controlsInit(standardButton, inheritButton, hm, null,
						formatForSetup);
			
			spinnerColumnCount.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					groupColumns.setEnabled(spinnerColumnCount.getSelection() > 1);
					setColumns(spinnerColumnCount.getSelection());
				}
			});
			
			inheritButton.addListener(SWT.Selection, new Listener() {
				@Override
				public void handleEvent(Event event) {
					groupColumns.setEnabled(!inheritButton.getSelection());
				}
			});
			
			standardButton.addListener(SWT.Selection, new Listener() {
				@Override
				public void handleEvent(Event event) {
					setColumns(spinnerColumnCount.getSelection());
				}
			});
		}
		
		columnlist = new ArrayList<Column>();
		
		{ 
			groupColumns = new Group(comp, SWT.NONE);
			groupColumns.setLayout(new GridLayout(9, false));
			groupColumns.setText(GuiMessages.Stileditor_PageLayout_Column_Definition + ":");
			
			setColumns(spinnerColumnCount.getSelection());
			
			String[] values = format.getAttribute("column-gaps").split(" ");
			String s;
			
			for (int i = 0; i < values.length; i++) { // 
				s = values[i];
				if (s.isEmpty())
					return;
				if (s.equalsIgnoreCase("auto")) { // no value for spinner needed
					setCombo((Combo) ghm.get(i)[1], s);
					ghm.get(i)[0].setEnabled(false);
				} else {
					setSpinnerCombo((Spinner) ghm.get(i)[0], (Combo) ghm.get(i)[1], s);
					ghm.get(i)[0].setEnabled(true);
				}
			}
		
			
			values = format.getAttribute("column-widths").split(" ");
			if (values[0] == "auto") { // auto
				for (int i = 0; i < values.length; i++) { // set all values to auto
					values[i] = "auto";
				}
			}
			
			for (int i = 0; i < values.length; i++) {
				s = values[i];
				if (s.isEmpty())
					return;
				if (s.equalsIgnoreCase("auto") || s.equalsIgnoreCase("*")) { // no value for spinner needed
					setCombo((Combo) cwhm.get(i)[1], s);
					cwhm.get(i)[0].setEnabled(false);
				} else {
					setSpinnerCombo((Spinner) cwhm.get(i)[0], (Combo) cwhm.get(i)[1], s);
					cwhm.get(i)[0].setEnabled(true);
				}
			}
				
			
			values = format.getAttribute("column-directions").split(" ");
			for (int i = 0; i < values.length; i++) {
				s = getLocalValue("column-directions", values[i]);
				if (s.isEmpty())
					return;
				setCombo((Combo) cdhm.get(i), s);
			}
			groupColumns.setEnabled(!inheritButton.getSelection());
		}
	}

	private void setColumns(int columnnumber) {
	
	int length = columnlist.size(); // actual number of gap items
	
	if (columnnumber < length) { // there are more existing items than needed => remove items; each column consists of 9 elements (at the moment)
		for (int i = length*9-1; i >= columnnumber*9; i--) {
			groupColumns.getChildren()[i].dispose();
		}
		
		for (int i = length-1; i >= columnnumber; i--) {
			columnlist.remove(i);
			ghm.remove(i);
			cwhm.remove(i);
			cdhm.remove(i);
		}
	} else { // columnnumber > length => we need more entries
		for (int i = length; i < columnnumber; i++) {
			columnlist.add(i, new Column());
		}
	
		for (int i = length; i < columnlist.size(); i++) { // draw new items for new columnlist
			addLabel(groupColumns, "Spalte " + (i+1) + ": ");
			addLabel(groupColumns, GuiMessages.Stileditor_PageLayout_Column_Widths);
			// width
			spinnercolumnwidth = new Spinner(groupColumns, SWT.NONE);
			spinnercolumnwidth.setLayoutData(getGD(0, 1, 50, 0));
			spinnercolumnwidth.setDigits(2);
			spinnercolumnwidth.setIncrement(100);
			spinnercolumnwidth.setMaximum(10000);
			spinnercolumnwidth.setMinimum(0);
			spinnercolumnwidth.setSelection(100);
			
			combocolumnwidth = new Combo(groupColumns, SWT.READ_ONLY);
			combocolumnwidth.setLayoutData(getGD(0, 1, 100, 0));
			combocolumnwidth.add("auto");
			for (String s : itemListUnits) {
				combocolumnwidth.add(s);
			}
			combocolumnwidth.add("%");
			combocolumnwidth.add("*");
			combocolumnwidth.addListener(SWT.Selection, new Listener() {
				@Override
				public void handleEvent(Event event) {
					int k = -1;
					for (int i = 0; i < cwhm.size(); i++) {
						if (cwhm.get(i)[1].equals(event.widget)) { // Look for matching combo box element in "ghm"
							k = i;
							break;
						}
					}
					
					if (k > -1) { // If found ...
						cwhm.get(k)[0].setEnabled(((Combo) cwhm.get(k)[1]).getSelectionIndex() > 0 && ((Combo) cwhm.get(k)[1]).getSelectionIndex() < 7 ); // activate spinner if selection in combo box is not "inherit"
						if (((Combo) cwhm.get(k)[1]).getSelectionIndex() == 0) { // "auto" selected
							for (int i = 0; i < cwhm.size(); i++) { // set all other combo boxes to "auto"
								((Combo) cwhm.get(i)[1]).select(0);
								((Spinner) cwhm.get(i)[0]).setEnabled(false);
							}
						}
					}
				}
			});
			
			
			String widthValue = columnlist.get(i).getWidth();
			if (widthValue == "auto" || widthValue == "*") { // for "auto" we do not need an active spinner
				spinnercolumnwidth.setEnabled(false);
				setCombo(combocolumnwidth, widthValue);
			} else {
				spinnercolumnwidth.setEnabled(true);
				setSpinnerCombo(spinnercolumnwidth, combocolumnwidth, widthValue);
			}
		
			cwhm.put(i, new Control[] { spinnercolumnwidth, combocolumnwidth }); // store new controls in ghm hash map
		
			// directions
			addLabel(groupColumns, GuiMessages.Stileditor_PageLayout_Column_Directions);
			combocolumndirection = new Combo(groupColumns, SWT.READ_ONLY);
			combocolumndirection.setLayoutData(getGD(0, 1, 150, 0));
			combocolumndirection.setItems(itemListColumndirections_local);
			
			String directionValue = columnlist.get(i).getDirection();
			setCombo(combocolumndirection, getLocalValue("column-directions", directionValue));
			
			cdhm.put(i, combocolumndirection); // store combo in cdhm hash map
				
			
			// gap
			addLabel(groupColumns, GuiMessages.Stileditor_PageLayout_Column_Gaps);
			spinnercolumngap = new Spinner(groupColumns, SWT.NONE);
			spinnercolumngap.setLayoutData(getGD(0, 1, 50, 0));
			spinnercolumngap.setDigits(2);
			spinnercolumngap.setIncrement(100);
			spinnercolumngap.setMaximum(10000);
			spinnercolumngap.setMinimum(0);
			
			combocolumngap = new Combo(groupColumns, SWT.READ_ONLY);
			combocolumngap.setLayoutData(getGD(0, 1, 50, 0));
			combocolumngap.add("auto");
			for (String s : itemListUnits) {
				combocolumngap.add(s);
			}
			combocolumngap.addListener(SWT.Selection, new Listener() {
				@Override
				public void handleEvent(Event event) {
					int k = -1;
					for (int i = 0; i < ghm.size(); i++) {
						if (ghm.get(i)[1].equals(event.widget)) { // Look for matching combo box element in "ghm"
							k = i;
							break;
						}
					}
					if (k > -1) { // If found ...
						ghm.get(k)[0].setEnabled(((Combo) ghm.get(k)[1]).getSelectionIndex() > 0); // activate spinner if selection in combo box is not "auto"
					}
				}
			});
			
			
			String gapValue = columnlist.get(i).getGap();
			
			if (gapValue == "auto") { // for "auto" we do not need an active spinner
				spinnercolumngap.setEnabled(false);
				setCombo(combocolumngap, gapValue);
			} else {
				spinnercolumngap.setEnabled(true);
				setSpinnerCombo(spinnercolumngap, combocolumngap, gapValue);
			}
		
			ghm.put(i, new Control[] { spinnercolumngap, combocolumngap }); // store new controls in ghm hash map
		}
		
		if (length > 0) { // if there were columns before, reactivate gap data for the second to last column
			groupColumns.getChildren()[groupColumns.getChildren().length-12].setVisible(true);
			ghm.get(length-1)[0].setVisible(true);
			ghm.get(length-1)[1].setVisible(true);
			
		}
	}
	// Remove last three elements from list, because we do not have a gap for the last column
	groupColumns.getChildren()[groupColumns.getChildren().length-3].setVisible(false);
		
	ghm.get(columnlist.size()-1)[0].setVisible(false);
	ghm.get(columnlist.size()-1)[1].setVisible(false);
				
	if (columnlist.size() == 1) {// only one column => remove elements
		ghm.get(0)[0].setVisible(false);
		ghm.get(0)[1].setVisible(false);
	}
	groupColumns.pack(true); // renew view
	
	}
		
	@Override
	public boolean controlValueVertify() {
		// TODO Auto-generated method stub
		return true;
	}
	
	class Column {
		private String width;
		private String direction;
		private String gap;

		public Column() {
			this.width = "auto";
			this.direction = "inherit";
			this.gap = "auto";
		}
		
		public String getWidth() {
			return this.width;
		}
		
		public String getDirection() {
			return this.direction;
		}
		
		public String getGap() {
			return this.gap;
		}
		
		public void setWidth(String w) {
			this.width = w;
		}
		
		public void setDirection(String d) {
			this.direction = d;
		}
		
		public void setGap(String g) {
			this.gap = g;
		}
	}
}
